﻿// copyright jyz.2024


#include "AuraProjectileSpell.h"

#include "AbilitySystemBlueprintLibrary.h"
#include "AbilitySystemComponent.h"
#include "AuraGameplayTags.h"
#include "Actor/AuraProjectile.h"
#include "Interaction/CombatInterface.h"

void UAuraProjectileSpell::ActivateAbility(
	const FGameplayAbilitySpecHandle Handle,
	const FGameplayAbilityActorInfo* ActorInfo,
	const FGameplayAbilityActivationInfo ActivationInfo,
	const FGameplayEventData* TriggerEventData)
{
	Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
}

void UAuraProjectileSpell::SpawnProjectile(const FVector& TargetLocation)
{
	//这里我们希望生成的抛射物是通过服务器生成的，客户端看到的只是一个复制的版本，
	//所以我们需要把抛射物的基类设置成网络同步的
	//判断是否是权威的服务器
	if(!GetAvatarActorFromActorInfo()->HasAuthority())
	{
		return;
	}
	
	ICombatInterface * CombatInterface = Cast<ICombatInterface>(GetAvatarActorFromActorInfo());
	
	checkf(CombatInterface,TEXT("该能力持有者需要继承ICombatInterface接口!!!"))

	AActor* AbilityOwning = GetOwningActorFromActorInfo();
	const FVector SocketLocation = CombatInterface->GetCombatSocketLocation();
	FRotator Rotator = (TargetLocation - SocketLocation).Rotation();
	Rotator.Pitch = 0.f;
	FTransform SpawnTransform;
	SpawnTransform.SetLocation(SocketLocation);
	SpawnTransform.SetRotation(Rotator.Quaternion());
	AAuraProjectile*Projectile = GetWorld()->SpawnActorDeferred<AAuraProjectile>(
		ProjectileClass,
		SpawnTransform,
		AbilityOwning,
		//（发起者或引发者）
		Cast<APawn>(AbilityOwning),
		ESpawnActorCollisionHandlingMethod::AlwaysSpawn,
		ESpawnActorScaleMethod::MultiplyWithRoot);
	
	//Todo: Give the Projectile a Gameplay Effect Spec for Causing Damage;
	//Todo: 为Projectile设置一种Gameplay Effect Spec来造成伤害；
	const UAbilitySystemComponent* SourceASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetAvatarActorFromActorInfo());
	FGameplayEffectContextHandle ContextHandle = SourceASC->MakeEffectContext();
	//设置GE的SourceObject：拥有这个能力的对象（例如怪物、主角等） 添加到GE的SourceObject中去
	ContextHandle.AddSourceObject(GetAvatarActorFromActorInfo());
	const FGameplayEffectSpecHandle SpecHandle = SourceASC->MakeOutgoingSpec(DamageEffectClass,GetAbilityLevel(),ContextHandle);
	const float ScaledDamage = Damage.GetValueAtLevel(GetAbilityLevel());
	UAbilitySystemBlueprintLibrary::AssignTagSetByCallerMagnitude(SpecHandle, FAuraGameplayTags::Get().Damage,ScaledDamage);
	Projectile->DamageEffectSpecHandle = SpecHandle;

	Projectile->FinishSpawning(SpawnTransform);

}
